package com.spn.blog.article.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.spn.blog.article.dao.mapper.ArticleMapper;
import com.spn.blog.common.dao.pojo.Article;
import com.spn.blog.common.vo.Result;
import com.spn.blog.service.article.ArticleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.List;

@Component
@Slf4j
public class ThreadService {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;


    //期望此操作在线程池执行，不会影响原有的主线程
    @Async("taskExecutor")//表示此方法在线程池中执行
    public void updateArticleViewCount(ArticleMapper articleMapper, Article article) {
        //获取传过来的原始值，进行+1
        // articleUpdate 里放着更新的内容
        // article 里放着旧的内容
        int viewCounts = article.getViewCounts();
        Article articleUpdate = new Article();
        articleUpdate.setViewCounts(viewCounts + 1);

        LambdaUpdateWrapper<Article> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Article::getId, article.getId());

        //设置一个 为了在多线程环境下 线程安全
        //采用乐观锁思想
        updateWrapper.eq(Article::getViewCounts, viewCounts);
        //update article set view_count=100 where view_count=99 and id=11
        articleMapper.update(articleUpdate, updateWrapper);

        //采用redis进行浏览量的增加
        //hash结构 key 浏览量标识 field 文章id  后面1 表示自增加1
        //因为redis中找不到hash的值，默认会从0开始，所以此处执行，需要一个前提：redis中的hash一直存在。
        //那么就需要定时器定时从数据库读取评论到redis。
        redisTemplate.opsForHash().increment("view_count",String.valueOf(article.getId()),1);
        //定时任务在ViewCountHandler中

        //还有一种方式是，redis自增之后，直接发送消息到消息队列中，由消息队列进行消费 来同步数据库，比定时任务要好一些

    }

    @Async("taskExecutor")
    public void updateArticleCommentCount(ArticleMapper articleMapper, Article article) {
        int commentCounts = article.getCommentCounts();
        Article articleUpdate = new Article();
        articleUpdate.setCommentCounts(commentCounts + 1);

        LambdaUpdateWrapper<Article> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Article::getId, article.getId());

        updateWrapper.eq(Article::getCommentCounts, commentCounts);
        //update article set comment_count=100 where comment_count=99 and id=11
        articleMapper.update(articleUpdate, updateWrapper);

        redisTemplate.opsForHash().increment("comment_count",String.valueOf(article.getId()),1);

    }
}
